#!/usr/bin/env python
from isolation import Board, game_as_text
from random import randint
from player_submission import OpenMoveEvalFn





class CustomPlayerMinMax:

    def __init__(self, search_depth=3, eval_fn=OpenMoveEvalFn()):
        self.eval_fn = eval_fn
        self.search_depth = search_depth

    def move(self, game, legal_moves, time_left):
        best_move, utility = self.minimax(game, time_left, depth=self.search_depth)
        return best_move

    def utility(self, game, maximizing_player):
        """Can be updated if desired. Not compulsory. """
        return self.eval_fn(game)

    def minimax(self, game, time_left, depth, maximizing_player=True):
        best_move = game.NOT_MOVED
        best_val = float('-inf')

        legal_moves = game.get_legal_moves()
        if not legal_moves:
            return best_move, best_val

        for a in legal_moves:
            best_val, best_move = max((best_val, best_move), (self.min_value(game.forecast_move(a)[0], time_left, depth-1), a))
        # raise NotImplementedError
        return best_move, best_val

    def max_value(self, game, time_left, depth, maximizing_player=True):
        legal_moves = game.get_legal_moves()
        if depth == 0 or not legal_moves:
            return self.eval_fn.score(game, maximizing_player)

        best_val = float('-inf')
        for a in legal_moves:
            best_val = max(best_val, self.min_value(game.forecast_move(a)[0], time_left, depth-1))

        return best_val

    def min_value(self, game, time_left, depth, maximizing_player=False):
        legal_moves = game.get_legal_moves()
        if depth == 0 or not legal_moves:
            return self.eval_fn.score(game, maximizing_player)

        best_val = float('inf')
        for a in legal_moves:
            best_val = min(best_val, self.max_value(game.forecast_move(a)[0], time_left, depth-1))

        return best_val

